import json
from typing import List

from sqlalchemy.exc import SQLAlchemyError

from constant.CommonConstant import SORT_ORDER_DESC, SORT_ORDER_ASC
from constant.UserConstant import DEFAULT_ROLE, ADMIN_ROLE
from my_decorator.AuthCheck import auth_check
from enums.UserRoleEnum import UserRoleEnum
from enums.AppReviewStatuesEnum import AppReviewStatuesEnum
from enums.AppScoringStategyEnum import AppScoringStrategyEnum
from controller.scoring_result.scoring_stategy.CustomScoreScoringStrategy import doGradeScore
from controller.scoring_result.scoring_stategy.CustomTestScoringStrategy import doTestScore
from controller.scoring_result.scoring_stategy.AITestScoringStrategy import AIdoTestScore
from flask import request, g

from models import User, db
from utils import JWT
from utils.ThreadLocal import ThreadLocalUtil
from .validate import *
from .. import userAnswer

userAnswerAddRequest = UserAnswerAddRequest()
userAnswerEditRequest = UserAnswerEditRequest()
userAnswerUpdateRequest = UserAnswerUpdateRequest()
userAnswerQueryRequest = UserAnswerQueryRequest()


# 添加用户答案
async def addUserAnswer():
    try:
        load_data = userAnswerAddRequest.load(request.json)
        appId = int(load_data.get('appId'))
        choices = json.dumps(load_data.get('choices'), ensure_ascii=False, indent=4)
        userAnswer = UserAnswer(
            appId=appId,
            choices=choices,
        )
        app:App = App.query.get(appId)
        if app is None:
            print(f"AppId {appId} 不存在对应的应用")
            baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
            return ApiResponse.error_from_baseResponse(baseResponse=baseResponse,
                                                       data=f"AppId {appId} 不存在对应的应用")
        if app.reviewStatus != AppReviewStatuesEnum.Pass.value[1]:
            print(f"AppId {appId} 的应用未通过审核")
            baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
            return ApiResponse.error_from_baseResponse(baseResponse=baseResponse,
                                                       data=f"AppId {appId} 的应用未通过审核")
        token = request.headers.get('Authorization')
        #user_map = JWT.JWTUtil.parse_token(token)
        user_map = getattr(g, 'user_map', {})
        user_id = user_map.get('id')
        userAnswer.userId = user_id
        userAnswer.appType = app.appType
        # 写入数据库
        try:
            db.session.add(userAnswer)
            db.session.commit()
            validate_userAnswer(userAnswer, True)
            choices:list[str] = load_data.get('choices')
            # 进行用户评分
            if app.scoringStrategy == AppScoringStrategyEnum.USER.get_value():
                if app.appType == AppEnum.Scoring_Category.value[1]:
                    doGradeScore(choices, app, userAnswer.id)
                else:
                    doTestScore(choices, app, userAnswer.id)
            else:
                await AIdoTestScore(choices, app, userAnswer.id)
            return ApiResponse.success()
        except SQLAlchemyError as e:
            db.session.rollback()
            print(f"添加App失败,{e}")
            baseResponse = BaseResponse.from_error_code(ErrorCode.OPERATION_ERROR)
            return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data=f"添加App失败")
    except SQLAlchemyError as e:
        print(f"添加App失败,{e}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.OPERATION_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data=f"添加App失败")
    except ValidationError as e:
        print(f"添加用户答案参数出错参数: {e}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data="添加用户答案参数出错参数")
    except Exception as e:
        print(f"{e}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.OPERATION_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data="未知错误")


# 删除用户答案
def deleteUserAnswer():
    id = request.args.get('id')
    if not isinstance(id,int):
        id = int(id)
    if id is None:
        print('删除用户答案id参数不存在!')
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data='删除用户答案id参数不存在!')
    user_map = ThreadLocalUtil.get()
    old_userAnswer: UserAnswer = UserAnswer.query.get(id)
    if old_userAnswer is None:
        print("用户答案不存在,无法删除")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data="用户答案不存在,无法删除")
    # 权限校验
    if user_map.get('id') != old_userAnswer.userId and user_map.get('user_role') != UserRoleEnum.ADMIN.get_value():
        print("你没有权限删除")
        baseResponse = BaseResponse.from_error_code(ErrorCode.NO_AUTH_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data="你没有权限删除")
    try:
        db.session.delete(old_userAnswer)
        db.session.commit()
        return ApiResponse.success()
    except SQLAlchemyError as e:
        db.session.rollback()
        print(f"删除错误:{str(e)}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.OPERATION_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data=f"删除错误:{str(e)}")


# 更新用户答案
@auth_check(required_roles = [UserRoleEnum.ADMIN.get_value()])
def updateUserAnswer():
    data = request.get_json()
    try:
        # DTO转换
        update_data = userAnswerUpdateRequest.load(data)
        userAnswer = UserAnswer()
        userAnswer.appId = update_data.get('appId')
        choices:List[str] = update_data.get('choices')
        userAnswer.choices = json.dumps(choices, ensure_ascii=False,indent=4)
        # 数据校验
        validate_userAnswer(userAnswer, True)
        # 判断是否存在
        id = update_data.get('id')
        if not isinstance(id, int):
            id = int(id)
        old_userAnswer:UserAnswer = UserAnswer.query.get(id)
        if old_userAnswer is None:
            print("用户答案不存在,无法更新")
            baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
            return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data="用户答案不存在,无法更新")
        # 操作数据库
        try:
            old_userAnswer.appId = userAnswer.appId
            old_userAnswer.choices = json.dumps(choices, ensure_ascii=False,indent=4)
            db.session.commit()
            return ApiResponse.success("更新成功！")
        except SQLAlchemyError as e:
            db.session.rollback()
            print(f"更新错误:{str(e)}")
            baseResponse = BaseResponse.from_error_code(ErrorCode.OPERATION_ERROR)
            return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data=f"更新错误:{str(e)}")
    except ValidationError as e:
        print(f"更新验证参数错误: {str(e)}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse,data=f"更新验证参数错误: {str(e)}")


# 获取用户答案(封装类)
def getUserAnswerVOById():
    id = request.args.get('id')
    if not isinstance(id,int):
        id = int(id)
    if id is None or id<=0:
        print('查找用户答案id参数非法!')
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data='查找用户答案id参数非法!')
    userAnswer:UserAnswer = UserAnswer.query.get(id)
    if userAnswer is None:
        print("用户答案不存在,无法获取")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data="用户答案不存在,无法获取")
    return ApiResponse.success(data=userAnswer.to_user_json_vo())


def query_database_for_all(query_data, user_map, isMy: bool = False):
    pageSize = query_data.get('pageSize')
    current = query_data.get('current')

    if user_map.get('user_role') == DEFAULT_ROLE:
        if pageSize > 20:
            print("用户访问异常")
            errorResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
            return ApiResponse.error_from_baseResponse(errorResponse, data="用户访问异常")
    query = UserAnswer.query
    # 查询条件
    query_filed = {
        'id': lambda q, v: q.filter(UserAnswer.id == v),
        'appType': lambda q, v: q.filter(UserAnswer.appType == v),
        'appId': lambda q, v: q.filter(UserAnswer.appId == v),
        'scoringStrategy': lambda q, v: q.filter(UserAnswer.scoringStrategy == v),
        'choices': lambda q, v: q.filter(UserAnswer.choices.contains(v)),
        'resultId': lambda q, v: q.filter(UserAnswer.resultId == v),
        'resultName': lambda q, v: q.filter(UserAnswer.resultName.contains(v)),
        'resultDesc': lambda q, v: q.filter(UserAnswer.resultDesc.contains(v)),
        'resultPicture': lambda q, v: q.filter(UserAnswer.resultPicture.contains(v)),
        'resultScore': lambda q, v: q.filter(UserAnswer.resultScore == v),
        'notId': lambda q, v: q.filter(UserAnswer.id != v),
        'userId': lambda q, v: q.filter(UserAnswer.userId == v),
        'isDelete': lambda q, v: q.filter(UserAnswer.isDelete == v),
    }
    # 构建查询
    for filed, condition_func in query_filed.items():
        value = query_data.get(filed)
        if value is not None:
            query = condition_func(query, value)
    # 给用户看到得是没有逻辑删除的
    if user_map.get('user_role') == DEFAULT_ROLE:
        query = query.filter(UserAnswer.isDelete == 0)
    # 如果是给自己看的
    if isMy:
        query = query.filter(UserAnswer.userId == user_map.get('id'))
        # 排序字段
    sort_fields = {
        'id': UserAnswer.id,
        'resultId': UserAnswer.resultId,
        'appId': UserAnswer.appId,
        'userId': UserAnswer.userId,
        'resultName':UserAnswer.resultName,
        'resultScore':UserAnswer.resultScore,
        'createTime': UserAnswer.createTime,
        'updateTime': UserAnswer.updateTime,
    }
    filed_name = query_data.get('sortField')
    if filed_name is not None:
        sortField = sort_fields.get(filed_name)
        sortOrder = query_data.get('sortOrder')
        if sortOrder == SORT_ORDER_DESC:
            sortField = sortField.desc()
        elif sortOrder == SORT_ORDER_ASC:
            sortField = sortField.asc()
        else:
            print("排序字段有误，参数校验失败")
            errorResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
            return ApiResponse.error_from_baseResponse(errorResponse, data="排序字段有误，参数校验失败")
        query = query.order_by(sortField)
    return query.paginate(page=current, per_page=pageSize)


# 分页获取用户答案列表(仅管理员可用)
@auth_check(required_roles = [UserRoleEnum.ADMIN.get_value()])
def listUserAnswerByPage():
    data = request.get_json()
    try:
        query_data = userAnswerQueryRequest.load(data)
        user_map = ThreadLocalUtil.get()
        pagination = query_database_for_all(query_data, user_map)
        base_data = {
            "total": pagination.total,
            "current": pagination.page,
            "pageSize": pagination.per_page,
            "pages": pagination.pages,
            # 这里要区分一下哪个是给用户看的，哪个是给管理员看的,用户不需要看到逻辑删除字段
            # 管理员不需要看到用户具体信息，
            "UserAnswerList": [(_userAnswer.to_admin_json_vo() if user_map.get(
                "user_role") == ADMIN_ROLE else _userAnswer.to_user_json_vo()) for _userAnswer in pagination.items],
        }
        return ApiResponse.success(data=base_data)
    except ValidationError as e:
        print(f"查询参数校验失败:{str(e)}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse,data=f"查询参数校验失败:{str(e)}")



# 分页获取用户答案列表封装类
def listUserAnswerVOByPage():
    data = request.get_json()
    try:
        query_data = userAnswerQueryRequest.load(data)
        user_map = ThreadLocalUtil.get()
        pagination = query_database_for_all(query_data, user_map)
        base_data = {
            "total": pagination.total,
            "current": pagination.page,
            "pageSize": pagination.per_page,
            "pages": pagination.pages,
            # 这里要区分一下哪个是给用户看的，哪个是给管理员看的,用户不需要看到逻辑删除字段
            # 管理员不需要看到用户具体信息，
            "UserAnswerList": [(_userAnswer.to_admin_json_vo() if user_map.get(
                "user_role") == ADMIN_ROLE else _userAnswer.to_user_json_vo()) for _userAnswer in pagination.items],
        }
        return ApiResponse.success(data=base_data)
    except ValidationError as e:
        print(f"查询参数校验失败:{str(e)}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse,data=f"查询参数校验失败:{str(e)}")


# 分页获取当前用户自己的答案列表
def listMyUserAnswerByPage():
    data = request.get_json()
    try:
        query_data = userAnswerQueryRequest.load(data)
        user_map = ThreadLocalUtil.get()
        pagination = query_database_for_all(query_data, user_map,True)
        base_data = {
            "total": pagination.total,
            "current": pagination.page,
            "pageSize": pagination.per_page,
            "pages": pagination.pages,
            # 这里要区分一下哪个是给用户看的，哪个是给管理员看的,用户不需要看到逻辑删除字段
            # 管理员不需要看到用户具体信息，
            "UserAnswerList": [_userAnswer.to_user_json_vo() for _userAnswer in pagination.items],
        }
        return ApiResponse.success(data=base_data)
    except ValidationError as e:
        print(f"查询参数校验失败:{str(e)}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse,data=f"查询参数校验失败:{str(e)}")

# 编辑用户答案
def editUserAnswer():
    data = request.get_json()
    try:
        # DTO转换
        update_data = userAnswerUpdateRequest.load(data)
        userAnswer = UserAnswer()
        userAnswer.appId = update_data.get('appId')
        choices: List[str] = update_data.get('choices')
        userAnswer.choices = json.dumps(choices, ensure_ascii=False, indent=4)
        # 数据校验
        validate_userAnswer(userAnswer, True)
        # 判断是否存在
        id = update_data.get('id')
        if not isinstance(id, int):
            id = int(id)
        old_userAnswer: UserAnswer = UserAnswer.query.get(id)
        if old_userAnswer is None:
            print("用户答案不存在,无法更新")
            baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
            return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data="用户答案不存在,无法更新")
        # 操作数据库
        try:
            old_userAnswer.appId = userAnswer.appId
            old_userAnswer.choices = choices
            db.session.commit()
            return ApiResponse.success("更新成功！")
        except SQLAlchemyError as e:
            db.session.rollback()
            print(f"更新错误:{str(e)}")
            baseResponse = BaseResponse.from_error_code(ErrorCode.OPERATION_ERROR)
            return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data=f"更新错误:{str(e)}")
    except ValidationError as e:
        print(f"更新验证参数错误: {str(e)}")
        baseResponse = BaseResponse.from_error_code(ErrorCode.PARAMS_ERROR)
        return ApiResponse.error_from_baseResponse(baseResponse=baseResponse, data=f"更新验证参数错误: {str(e)}")

